package debtbundler.domain.entity.impl;


import debtbundler.domain.entity.BalanceBook;
import debtbundler.domain.entity.BalanceSheet;
import debtbundler.domain.entity.Debt;
import debtbundler.domain.entity.Payment;
import debtbundler.domain.entity.SharedCost;
import debtbundler.domain.entity.Person;
import debtbundler.domain.entity.Share;
import debtbundler.domain.entity.Signature;

/**
 * A facade that allows clients to be independent of implementations of domain entities.
 * However, use only with instances created by this <code>EntityManager</code>.
 * 
 * @author Anssi
 */
public class EntityManager {
	
	/**
	 * Creates a new shared cost.
	 * 
	 * @return	a new shared cost
	 */
	public static SharedCost createSharedCost() {
		SharedCostImpl cost = new SharedCostImpl();
		cost.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return cost;
	}
	
	/**
	 * Creates a new person.
	 * 
	 * @return	 a new person
	 */
	public static Person createPerson() {
		PersonImpl person = new PersonImpl();
		person.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return person;
	}
	
	/**
	 * Creates a new payment for shared cost and adds it to the person
	 * and to the cost.
	 * 
	 * @param person		the person paying the payment
	 * @param sharedCost	the shared cots
	 * @return				a new payment
	 */
	public static Payment createPayment(Person person, SharedCost sharedCost) {
		PersonImpl personImpl = (PersonImpl)person;
		SharedCostImpl costImpl = (SharedCostImpl)sharedCost;
		PaymentImpl payment = new PaymentImpl(personImpl, costImpl);
		personImpl.addPayment(payment);
		costImpl.addPayment(payment);
		payment.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return payment;
	}
	
	/**
	 * Creates a new share of costs and adds it to the person
	 * and to the cost.
	 * 
	 * @param person	the person for whom to create a share
	 * @param sharedCost		sharedCost for which to create a share
	 * @return			a new share
	 */	
	public static Share createShare(Person person, SharedCost sharedCost) {
		PersonImpl personImpl = (PersonImpl)person;
		SharedCostImpl poolImpl = (SharedCostImpl)sharedCost;
		ShareImpl share = new ShareImpl(personImpl, poolImpl);
		personImpl.addShare(share);
		poolImpl.addShare(share);
		share.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return share;
	}
		
	/**
	 * Creates a new debt and adds it to the debtor and the creditor.
	 * 
	 * @param debtor	person who owes money
	 * @param creditor	person to whom money is owed
	 * @return			debt between <code>debtor</code> and <code>creditor</code>
	 */
	public static Debt createDebt(Person debtor, Person creditor) {
		PersonImpl debtorImpl = (PersonImpl)debtor;
		PersonImpl creditorImpl = (PersonImpl)creditor;
		DebtImpl debt = new DebtImpl(debtorImpl, creditorImpl);
		debtorImpl.addDebt(debt);
		creditorImpl.addDebt(debt);
		debt.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return debt;
	}	
	
	/**
	 * Creates a new balance sheet.
	 * 
	 * @return	a new balance sheet
	 */
	public static BalanceSheet createBalanceSheet() {
		BalanceSheetImpl sheet = new BalanceSheetImpl();
		sheet.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return sheet;
	}

	/**
	 * Creates a new balance book.
	 * 
	 * @return	a new balance book
	 */
	public static BalanceBook createBalanceBook() {
		BalanceBookImpl book = new BalanceBookImpl();
		book.addEntityListener(EntityUpdateNotifier.getTheInstance());
		return book;
	}

	/**
	 * Creates a new signature.
	 * 
	 * @return	a new signature
	 */
	public static Signature createSignature() {
		return new SignatureImpl();
	}

}
